package com.bawei.module_publish.ui


import android.content.Intent
import android.media.MediaPlayer
import android.os.AsyncTask
import android.os.Handler
import android.util.DisplayMetrics
import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import android.view.ViewGroup
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.view.WindowManager
import android.widget.CompoundButton
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.VideoView
import com.alibaba.android.arouter.facade.annotation.Route
import com.bawei.lib_mvi.base.BaseActivity
import com.bawei.module_publish.R
import com.bawei.module_publish.databinding.ActivityVideoTrimBinding
import com.bawei.module_publish.utils.Config
import com.bawei.module_publish.utils.GetPathFromUri
import com.bawei.module_publish.utils.MediaStoreUtils
import com.bawei.module_publish.weiget.CustomProgressDialog
import com.qiniu.pili.droid.shortvideo.PLMediaFile
import com.qiniu.pili.droid.shortvideo.PLShortVideoTrimmer
import com.qiniu.pili.droid.shortvideo.PLVideoFrame
import com.qiniu.pili.droid.shortvideo.PLVideoSaveListener
import java.io.File
import java.util.Locale
import java.util.concurrent.TimeUnit

@Route(path = "/publish/VideoTrimActivity")
class VideoTrimActivity : BaseActivity() {

    private val binding: ActivityVideoTrimBinding by lazy {
        ActivityVideoTrimBinding.inflate(layoutInflater)
    }

    override fun getLayoutRootView(): View {
        return binding.root
    }

    companion object {
        const val TAG: String = "VideoTrimActivity"
        const val SLICE_COUNT: Int = 8
    }

    private lateinit var mShortVideoTrimmer: PLShortVideoTrimmer
    private lateinit var mMediaFile: PLMediaFile
    private lateinit var mFrameListView: LinearLayout
    private lateinit var mHandlerLeft: View
    private lateinit var mHandlerRight: View
    private lateinit var mProcessingDialog: CustomProgressDialog
    private lateinit var mPreview: VideoView

    private var mSelectedBeginMs: Long = 0
    private var mSelectedEndMs: Long = 0
    private var mDurationMs: Long = 0

    private var mVideoFrameCount = 0
    private var mSlicesTotalLength = 0

    private val mHandler = Handler()

    private var mFastModeRadioBtn: RadioButton? = null
    private var mEncodeTypeRadioGroup: RadioGroup? = null
    private var mAccurateHwEncodeEnabled = true


    override fun initView() {
        mProcessingDialog = CustomProgressDialog(this)
        mProcessingDialog!!.setOnCancelListener { dialog -> mShortVideoTrimmer!!.cancelTrim() }

        val intent = Intent()
        intent.setAction(Intent.ACTION_OPEN_DOCUMENT)
        intent.setType("video/*")
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        startActivityForResult(intent, 0)

    }

    override fun onResume() {
        super.onResume()
        play()
    }

    override fun onPause() {
        super.onPause()
        stopTrackPlayProgress()
    }

    override fun onDestroy() {
        super.onDestroy()
        if (mShortVideoTrimmer != null) {
            mShortVideoTrimmer!!.destroy()
        }
        if (mMediaFile != null) {
            mMediaFile!!.release()
        }
    }

    private fun init(videoPath:String){
        val duration = findViewById<TextView>(R.id.duration)
        mPreview = findViewById<VideoView>(R.id.preview)
        mFastModeRadioBtn = (findViewById<View>(R.id.mode_fast) as RadioButton)
        mEncodeTypeRadioGroup = findViewById<RadioGroup>(R.id.encode_type)
        mFastModeRadioBtn!!.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { buttonView: CompoundButton?, isChecked: Boolean ->
            mEncodeTypeRadioGroup!!.setVisibility(
                if (isChecked) View.GONE else View.VISIBLE
            )
        })
        mEncodeTypeRadioGroup!!.setOnCheckedChangeListener(RadioGroup.OnCheckedChangeListener { group: RadioGroup?, checkedId: Int ->
            mAccurateHwEncodeEnabled = checkedId == R.id.hw_encode
        })

        mShortVideoTrimmer = PLShortVideoTrimmer(this, videoPath, Config.TRIM_FILE_PATH)
        mMediaFile = PLMediaFile(videoPath)

        mSelectedEndMs = mMediaFile!!.getDurationMs().also { mDurationMs = it }
        duration.text = "时长: " + formatTime(mDurationMs)
        Log.i(TAG, "video duration: $mDurationMs")

        mVideoFrameCount = mMediaFile!!.getVideoFrameCount(false)
        Log.i(TAG, "video frame count: $mVideoFrameCount")

        adjustSurfaceSize()
        mPreview!!.setVideoPath(videoPath)
        mPreview!!.setOnCompletionListener(MediaPlayer.OnCompletionListener { mediaPlayer: MediaPlayer? -> play() })

        initVideoFrameList()
    }
    private fun startTrackPlayProgress() {
        stopTrackPlayProgress()
        mHandler.postDelayed(object : Runnable {
            override fun run() {
                if (mPreview!!.currentPosition >= mSelectedEndMs) {
                    mPreview!!.seekTo(mSelectedBeginMs.toInt())
                }
                mHandler.postDelayed(this, 100)
            }
        }, 100)
    }

    private fun stopTrackPlayProgress() {
        mHandler.removeCallbacksAndMessages(null)
    }

    private fun play() {
        if (mPreview != null) {
            mPreview!!.seekTo(mSelectedBeginMs.toInt())
            mPreview!!.start()
            startTrackPlayProgress()
        }
    }
    private fun adjustSurfaceSize() {
        val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        val outMetrics = DisplayMetrics()
        windowManager.defaultDisplay.getMetrics(outMetrics)

        val screenWidth = outMetrics.widthPixels
        val videoWidth: Int
        val videoHeight: Int
        if (mMediaFile!!.getVideoRotation() / 90 % 2 == 1) {
            videoWidth = mMediaFile!!.getVideoHeight()
            videoHeight = mMediaFile!!.getVideoWidth()
        } else {
            videoWidth = mMediaFile!!.getVideoWidth()
            videoHeight = mMediaFile!!.getVideoHeight()
        }
        val videoAspectRatio = videoWidth.toFloat() / videoHeight
        var displayWidth = 0
        var displayHeight = 0
        if (videoAspectRatio < 1) {
            // 竖屏视频
            displayWidth = (screenWidth * videoAspectRatio).toInt()
            displayHeight = screenWidth
        } else if (videoAspectRatio > 1) {
            // 横屏视频
            displayWidth = screenWidth
            displayHeight = (screenWidth / videoAspectRatio).toInt()
        } else {
            displayWidth = screenWidth
            displayHeight = screenWidth
        }
        val layoutParams: ViewGroup.LayoutParams = mPreview.getLayoutParams()
        layoutParams.height = displayHeight
        layoutParams.width = displayWidth
        mPreview.setLayoutParams(layoutParams)
    }

    private fun initVideoFrameList() {
        mFrameListView = findViewById<LinearLayout>(R.id.video_frame_list)
        mHandlerLeft = findViewById<View>(R.id.handler_left)
        mHandlerRight = findViewById<View>(R.id.handler_right)

        mHandlerLeft!!.setOnTouchListener(OnTouchListener { v, event ->
            val action = event.action
            val viewX = v.x
            val movedX = event.x
            val finalX = viewX + movedX
            updateHandlerLeftPosition(finalX)

            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
                calculateRange()
            }
            true
        })

        mHandlerRight!!.setOnTouchListener(OnTouchListener { v, event ->
            val action = event.action
            val viewX = v.x
            val movedX = event.x
            val finalX = viewX + movedX
            updateHandlerRightPosition(finalX)

            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
                calculateRange()
            }
            true
        })

        mFrameListView!!.getViewTreeObserver()
            .addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    mFrameListView!!.getViewTreeObserver().removeOnGlobalLayoutListener(this)

                    val sliceEdge: Int = mFrameListView!!.getWidth() / VideoTrimActivity.SLICE_COUNT
                    mSlicesTotalLength = sliceEdge * VideoTrimActivity.SLICE_COUNT
                    Log.i(VideoTrimActivity.TAG, "slice edge: $sliceEdge")
                    val px = TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_DIP,
                        2f,
                        resources.displayMetrics
                    )

                }
            })
    }

    private fun updateHandlerLeftPosition(movedPosition: Float) {
        val lp = mHandlerLeft!!.getLayoutParams() as RelativeLayout.LayoutParams
        if ((movedPosition + mHandlerLeft.getWidth()) > mHandlerRight.getX()) {
            lp.leftMargin = (mHandlerRight.getX() - mHandlerLeft.getWidth()).toInt()
        } else if (movedPosition < 0) {
            lp.leftMargin = 0
        } else {
            lp.leftMargin = movedPosition.toInt()
        }
        mHandlerLeft.setLayoutParams(lp)
    }

    private fun updateHandlerRightPosition(movedPosition: Float) {
        val lp = mHandlerRight.getLayoutParams() as RelativeLayout.LayoutParams
        lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0)
        lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
        if (movedPosition < (mHandlerLeft.getX() + mHandlerLeft.getWidth())) {
            lp.leftMargin = (mHandlerLeft.getX() + mHandlerLeft.getWidth()).toInt()
        } else if ((movedPosition + (mHandlerRight.getWidth() / 2)) > (mFrameListView.getX() + mSlicesTotalLength)) {
            lp.leftMargin =
                ((mFrameListView.getX() + mSlicesTotalLength) - (mHandlerRight.getWidth() / 2)).toInt()
        } else {
            lp.leftMargin = movedPosition.toInt()
        }
        mHandlerRight.setLayoutParams(lp)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == RESULT_OK && data!!.data != null) {
            val selectedFilepath: String = GetPathFromUri.getRealPathFromURI(this, data.data)
            Log.i(VideoTrimActivity.TAG, "Select file: $selectedFilepath")
            if (selectedFilepath != null && "" != selectedFilepath) {
                init(selectedFilepath)
            }
        } else {
            finish()
        }
    }

    private fun clamp(origin: Float): Float {
        if (origin < 0) {
            return 0F
        }
        if (origin > 1) {
            return 1F
        }
        return origin
    }

    private fun calculateRange() {
        var beginPercent: Float =
            1.0f * ((mHandlerLeft.getX() + mHandlerLeft.getWidth() / 2) - mFrameListView.getX()) / mSlicesTotalLength
        var endPercent: Float =
            1.0f * ((mHandlerRight.getX() + mHandlerRight.getWidth() / 2) - mFrameListView.getX()) / mSlicesTotalLength
        beginPercent = clamp(beginPercent)
        endPercent = clamp(endPercent)

        Log.i(
            VideoTrimActivity.TAG,
            "begin percent: $beginPercent end percent: $endPercent"
        )

        mSelectedBeginMs = (beginPercent * mDurationMs).toLong()
        mSelectedEndMs = (endPercent * mDurationMs).toLong()

        Log.i(VideoTrimActivity.TAG, "new range: $mSelectedBeginMs-$mSelectedEndMs")
        updateRangeText()
        play()
    }

    fun onDone(v: View?) {
        Log.i(
            VideoTrimActivity.TAG,
            ("trim to file path: " + Config.TRIM_FILE_PATH).toString() + " range: " + mSelectedBeginMs + " - " + mSelectedEndMs
        )
        mProcessingDialog.show()
        mProcessingDialog.setProgress(0)

        val mode =
            if ((findViewById<View>(R.id.mode_fast) as RadioButton).isChecked) PLShortVideoTrimmer.TRIM_MODE.FAST else PLShortVideoTrimmer.TRIM_MODE.ACCURATE
        if (mode == PLShortVideoTrimmer.TRIM_MODE.ACCURATE) {
            mShortVideoTrimmer.trim(
                mSelectedBeginMs,
                mSelectedEndMs,
                mAccurateHwEncodeEnabled,
                mVideoSaveListener
            )
        } else {
            mShortVideoTrimmer.trim(mSelectedBeginMs, mSelectedEndMs, mode, mVideoSaveListener)
        }
    }

    fun onBack(v: View?) {
        finish()
    }

    private fun formatTime(timeMs: Long): String {
        return String.format(
            Locale.CHINA, "%02d:%02d",
            TimeUnit.MILLISECONDS.toMinutes(timeMs),
            TimeUnit.MILLISECONDS.toSeconds(timeMs) - TimeUnit.MINUTES.toSeconds(
                TimeUnit.MILLISECONDS.toMinutes(
                    timeMs
                )
            )
        )
    }

    private fun updateRangeText() {
        val range = findViewById<TextView>(R.id.range)
        range.text =
            "剪裁范围: " + formatTime(mSelectedBeginMs) + " - " + formatTime(mSelectedEndMs)
    }

    private val mVideoSaveListener: PLVideoSaveListener = object : PLVideoSaveListener {
        override fun onSaveVideoSuccess(path: String) {
            MediaStoreUtils.storeVideo(this@VideoTrimActivity, File(path), "video/mp4")
            mProcessingDialog.dismiss()
          //  VideoEditActivity.start(this@VideoTrimActivity, path)
        }

        override fun onSaveVideoFailed(errorCode: Int) {
            runOnUiThread {
                mProcessingDialog.dismiss()
               // ToastUtils.toastErrorCode(errorCode)
            }
        }

        override fun onSaveVideoCanceled() {
            mProcessingDialog.dismiss()
        }

        override fun onProgressUpdate(percentage: Float) {
            runOnUiThread { mProcessingDialog.setProgress((100 * percentage).toInt()) }
        }
    }

}